//go:build windows

package store

import (
	"fmt"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
)

// Windows API 常量
const (
	CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
	CERT_STORE_PROV_SYSTEM          = 10
	CERT_STORE_OPEN_EXISTING_FLAG   = 0x00004000
	CERT_FIND_HASH                  = 0x00010000
	X509_ASN_ENCODING               = 0x00000001
	PKCS_7_ASN_ENCODING             = 0x00010000
)

var (
	crypt32 = windows.NewLazySystemDLL("crypt32.dll")

	procCertOpenStore        = crypt32.NewProc("CertOpenStore")
	procCertCloseStore       = crypt32.NewProc("CertCloseStore")
	procCertEnumCertificates = crypt32.NewProc("CertEnumCertificatesInStore")
	procCertFindCertificate  = crypt32.NewProc("CertFindCertificateInStore")
	procCertDeleteCertificate = crypt32.NewProc("CertDeleteCertificateFromStore")
	procCertAddEncodedCertificate = crypt32.NewProc("CertAddEncodedCertificateToStore")
)

// CERT_CONTEXT 结构（简化版）
type CERT_CONTEXT struct {
	dwCertEncodingType uint32
	pbCertEncoded      *byte
	cbCertEncoded      uint32
	pCertInfo          uintptr
	hCertStore         windows.Handle
}

// Store 表示 Windows 证书存储的实际实现
type storeImpl struct {
	name   StoreName
	handle windows.Handle
}

// OpenStore 打开指定的证书存储
func OpenStore(name StoreName) (*Store, error) {
	storeName, err := syscall.UTF16PtrFromString(string(name))
	if err != nil {
		return nil, fmt.Errorf("转换存储名称失败: %w", err)
	}

	ret, _, err := procCertOpenStore.Call(
		uintptr(CERT_STORE_PROV_SYSTEM),
		0,
		0,
		uintptr(CERT_SYSTEM_STORE_LOCAL_MACHINE|CERT_STORE_OPEN_EXISTING_FLAG),
		uintptr(unsafe.Pointer(storeName)),
	)

	if ret == 0 {
		return nil, fmt.Errorf("打开证书存储失败 %s: %w", name, err)
	}

	return &Store{
		name: name,
		impl: &storeImpl{
			name:   name,
			handle: windows.Handle(ret),
		},
	}, nil
}

// FindByThumbprint 根据指纹查找证书
func (s *storeImpl) findByThumbprint(thumbprint string) (*Certificate, error) {
	// 将十六进制字符串转换为字节数组
	hash, err := hexToBytes(thumbprint)
	if err != nil {
		return nil, fmt.Errorf("无效的证书指纹: %w", err)
	}

	// CRYPT_HASH_BLOB 结构
	hashBlob := struct {
		cbData uint32
		pbData *byte
	}{
		cbData: uint32(len(hash)),
		pbData: &hash[0],
	}

	ret, _, err := procCertFindCertificate.Call(
		uintptr(s.handle),
		uintptr(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING),
		0,
		uintptr(CERT_FIND_HASH),
		uintptr(unsafe.Pointer(&hashBlob)),
		0,
	)

	if ret == 0 {
		return nil, fmt.Errorf("未找到证书: %s", thumbprint)
	}

	certContext := (*CERT_CONTEXT)(unsafe.Pointer(ret))
	return s.certContextToCertificate(certContext)
}

// Add 添加证书到存储
func (s *storeImpl) add(cert *Certificate) error {
	ret, _, err := procCertAddEncodedCertificate.Call(
		uintptr(s.handle),
		uintptr(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING),
		uintptr(unsafe.Pointer(&cert.RawData[0])),
		uintptr(len(cert.RawData)),
		uintptr(0x00000003), // CERT_STORE_ADD_REPLACE_EXISTING
		0,
	)

	if ret == 0 {
		return fmt.Errorf("添加证书失败: %w", err)
	}

	return nil
}

// Remove 从存储中移除证书
func (s *storeImpl) remove(thumbprint string) error {
	cert, err := s.findByThumbprint(thumbprint)
	if err != nil {
		return err
	}

	// 获取证书上下文
	hash, _ := hexToBytes(thumbprint)
	hashBlob := struct {
		cbData uint32
		pbData *byte
	}{
		cbData: uint32(len(hash)),
		pbData: &hash[0],
	}

	ret, _, err := procCertFindCertificate.Call(
		uintptr(s.handle),
		uintptr(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING),
		0,
		uintptr(CERT_FIND_HASH),
		uintptr(unsafe.Pointer(&hashBlob)),
		0,
	)

	if ret == 0 {
		return fmt.Errorf("未找到证书: %s", thumbprint)
	}

	certContext := (*CERT_CONTEXT)(unsafe.Pointer(ret))

	// 删除证书
	ret2, _, err2 := procCertDeleteCertificate.Call(uintptr(unsafe.Pointer(certContext)))
	if ret2 == 0 {
		return fmt.Errorf("删除证书失败: %w", err2)
	}

	_ = cert // 避免未使用变量警告
	return nil
}

// List 列出存储中的所有证书
func (s *storeImpl) list() ([]*Certificate, error) {
	var certs []*Certificate
	var prevContext uintptr = 0

	for {
		ret, _, _ := procCertEnumCertificates.Call(
			uintptr(s.handle),
			prevContext,
		)

		if ret == 0 {
			break // 枚举完成
		}

		certContext := (*CERT_CONTEXT)(unsafe.Pointer(ret))
		cert, err := s.certContextToCertificate(certContext)
		if err != nil {
			continue // 跳过无效证书
		}

		certs = append(certs, cert)
		prevContext = ret
	}

	return certs, nil
}

// Close 关闭证书存储
func (s *storeImpl) close() error {
	if s.handle != 0 {
		procCertCloseStore.Call(uintptr(s.handle), 0)
		s.handle = 0
	}
	return nil
}

// certContextToCertificate 将 CERT_CONTEXT 转换为 Certificate
func (s *storeImpl) certContextToCertificate(ctx *CERT_CONTEXT) (*Certificate, error) {
	// 提取证书数据
	certData := make([]byte, ctx.cbCertEncoded)
	for i := uint32(0); i < ctx.cbCertEncoded; i++ {
		certData[i] = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ctx.pbCertEncoded)) + uintptr(i)))
	}

	// TODO: 解析证书以提取 Subject、Issuer、SerialNumber、Thumbprint
	// 可以使用 crypto/x509 包解析证书
	// cert, err := x509.ParseCertificate(certData)

	return &Certificate{
		Thumbprint:   "", // TODO: 计算 SHA1 指纹
		Subject:      "", // TODO: 从证书提取
		Issuer:       "", // TODO: 从证书提取
		SerialNumber: "", // TODO: 从证书提取
		RawData:      certData,
		Store:        s.name,
	}, nil
}

// hexToBytes 将十六进制字符串转换为字节数组
func hexToBytes(hex string) ([]byte, error) {
	if len(hex)%2 != 0 {
		return nil, fmt.Errorf("无效的十六进制字符串长度")
	}

	bytes := make([]byte, len(hex)/2)
	for i := 0; i < len(hex); i += 2 {
		var b byte
		_, err := fmt.Sscanf(hex[i:i+2], "%02X", &b)
		if err != nil {
			return nil, err
		}
		bytes[i/2] = b
	}
	return bytes, nil
}
